home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.006 / xemacs-1 / lib / xemacs-19.13 / lisp / energize / energize-visit-use.el < prev    next >
Encoding:
Text File  |  1994-12-09  |  26.8 KB  |  683 lines

  1. ;;; -*- Mode:Emacs-Lisp -*-
  2. ;;; Copyright ⌐ 1992-1993 by Lucid, Inc.  All Rights Reserved.
  3.  
  4. ;; Load this file and ^X-\ (back-slash) gets bound to a
  5. ;; command that visit all the places where a language element is used.  
  6. ;; It can be started from the Le-Browser buffer of that language element
  7. ;; or from a toplevel from defining the element.
  8. ;; 
  9. ;; The visit happens as follows:
  10. ;;   - the 1st ^X-\ jumps to the beginning of the definition of the 1sr user.
  11. ;;   - then search-forward inside the first user for the name of the
  12. ;;     language element that was in the le-browser buffer.
  13. ;;   - the 2rd one searches again etc.. until no more match is found inside
  14. ;;     the body of the 1 user.
  15. ;;   - after the last match is seen the next user of the LE is visited 
  16. ;;     the same way.
  17. ;; 
  18. ;; If you want to start revisiting while a previous visit is not terminated do
  19. ;; ^U-^X-\ in another (or the same) le-browser buffer.
  20. ;; 
  21. ;; If you position the point on a User in the LE Browser buffer before doing
  22. ;; ^X-\, that use will become the next one shown.
  23. ;;
  24. ;; energize-next-use-previous, ^U-1-^X-\, backs up one use
  25. ;;
  26. ;; It's quite crude and the UI could be improved in different ways.  
  27. ;; What about:
  28. ;;   - Allow for stacking of visits so that you can recursively 
  29. ;;     visit another LE while one is being visited.
  30. ;;   - Highlight all the occurences of the LE-name inside the body of the user.
  31. ;;   - Deal with *alternatives*
  32.  
  33. (defvar energize-next-use-show-le-browser t
  34.   "*If t energize-next-use-command will show both the next use and the le-browser buffer")
  35.  
  36. (defvar energize-next-use-search-by-file nil ;; default is off cause on is slow
  37.   "*If t energize-next-use-command will show all uses in a file before going to
  38. the next file")
  39.  
  40. (defvar energize-next-use-command-name ())
  41. (defvar energize-next-use-label ())
  42. (defvar energize-next-use-name ())
  43. (defvar energize-next-use-from-mark ())
  44. (defvar energize-next-use-source-start-mark ())
  45. (defvar energize-next-use-source-end-mark ())
  46. (defvar energize-next-use-source-current-mark ())
  47. (defvar energize-next-use-current-file ())
  48. (defvar energize-next-use-file-began-mark ())
  49. (defvar energize-next-use-from-extent-cache ())
  50. (defvar energize-next-use-history ())
  51. (defvar energize-next-use-history-pointer ())
  52. (defvar energize-next-use-marker-heap ())
  53.  
  54. ;; remember markers we allocate so we can clean them up
  55. (defun energize-next-use-make-a-marker ()
  56.   (let ((m (make-marker)))
  57.     (setq energize-next-use-marker-heap
  58.       (cons m energize-next-use-marker-heap))
  59.     m))
  60.  
  61. (defun energize-next-use-copy-a-marker (mark)
  62.   (let ((m (copy-marker mark)))
  63.     (setq energize-next-use-marker-heap
  64.       (cons m energize-next-use-marker-heap))
  65.     m))
  66.  
  67. (defun energize-next-use-cleanup-markers ()
  68.   (while energize-next-use-marker-heap
  69.     (set-marker (car energize-next-use-marker-heap) nil)
  70.     (setq energize-next-use-marker-heap (cdr energize-next-use-marker-heap))))
  71.  
  72. (defun extent-after (pos)
  73.   (let ((extent (next-extent (current-buffer))))
  74.     (while (and extent (< (extent-start-position extent) pos))
  75.       (setq extent (next-extent extent)))
  76.     extent))
  77.  
  78. (defun energize-next-use-start-pos ()
  79.   (save-excursion
  80.     (goto-char (point-min))
  81.     (if (search-forward energize-next-use-label () t)
  82.     (point)
  83.       ())))
  84.  
  85. ;; see if we are in the LE Browser buffer of the object we are looking at
  86. ;; uses of.  If so, capture the position as a possible place to find the
  87. ;; next user, rather than take the first or next in sequence.
  88. (defun energize-next-use-start-pos-offset ()
  89.   ;; energize-next-use-from-mark is NULL iff this is called from
  90.   ;; energize-next-use-init - in that case assume that if we are in a LEB
  91.   ;; it is the one we will be using
  92.   (if (if (and energize-next-use-from-mark
  93.            (marker-buffer energize-next-use-from-mark))
  94.       (eq (current-buffer) (marker-buffer energize-next-use-from-mark))
  95.     (eq major-mode 'energize-browser-mode))
  96.       (save-excursion
  97.     (beginning-of-line)
  98.     (point))))
  99.  
  100. (defun energize-next-use-get-name (name)
  101.   (let ((colon (- (length name) 1)))
  102.     (while (and (> colon 0) (not (eq (aref name colon) ?:)))
  103.       (setq colon (- colon 1)))
  104.     (if (= (aref name colon) ?:)
  105.     (substring name (+ colon 1))
  106.       name)))
  107.  
  108. ;; cache the extents (and later the results of following them to the
  109. ;; source buffer) to avoid calling the server too many times
  110. ;; returns nil if the extent does not have a "source" menu option
  111. ;; returns the cache entry otherwise
  112. (defun energize-next-use-valid-from-extent-p (buff extent)
  113.   (let ((cache-entry (assoc extent energize-next-use-from-extent-cache)))
  114.     (if (not cache-entry)
  115.     (if (energize-list-menu buff extent ()
  116.                 energize-next-use-command-name)
  117.         (setq energize-next-use-from-extent-cache
  118.           (cons (setq cache-entry (list extent))
  119.             energize-next-use-from-extent-cache))))
  120.     cache-entry))
  121.  
  122. ;; decide what use to look at next.  current is nil if called from
  123. ;; energize-next-use-next, else it is the presumed first extent for
  124. ;; energize-next-use-from-mark passed from energize-next-use-init
  125. ;; wanted-pos is the position of the cursor in the LE Browser of the
  126. ;; object being looked for, or nil if the cursor is not in that buffer
  127. ;; if wanted-pos is non-nil it means we will consider restarting the
  128. ;; search at the user indicated by that position.  Otherwise, we just
  129. ;; return current.  If this is nil too, it means just continue searching
  130. ;; as before.  If not, it means continue initializing as before.
  131. ;;
  132. ;; returns an extent to be used to set energize-next-use-from-mark or nil
  133. (defun energize-next-use-adjust-for-start-offset (current wanted-pos)
  134.   ;; assumes we're in the LE browser buffer (we may not have been when
  135.   ;; the value of wanted-pos was determined)
  136.   (if wanted-pos
  137.       (let ((end-pos (energize-next-use-end-pos))
  138.         ;; ok will be set to the first extent found that is actually
  139.         ;; a user
  140.         (ok nil)
  141.         (try (or current (extent-after (energize-next-use-start-pos)))))
  142.     ;; loop will exit if an actual user extent is found that follows
  143.     ;; the wanted-pos - if we go out of bounds, try is set to nil
  144.     ;; else it is the desired extent on exit from the loop
  145.     (while (and try
  146.             (or (< (extent-start-position try) end-pos)
  147.             (setq try nil))
  148.             (not
  149.              (and
  150.               ;; try is a valid user extent if this menu exists
  151.               (energize-next-use-valid-from-extent-p
  152.                (current-buffer) try)
  153.               ;; but it might be before wanted-pos,
  154.               (or (> (extent-end-position try) wanted-pos)
  155.               ;; in which case remember it as ok unless
  156.               ;; ok was already set 
  157.               (and (setq ok (or ok try)) nil)))))
  158.       (setq try (next-extent try)))
  159.     ;; return try or if we were called from init, return ok
  160.     ;; else return nil to mean continue searching in current sequence
  161.     (or try (and current ok)))
  162.     current))
  163.  
  164. (defun energize-next-use-set-marks (extent buffer)
  165.   (if (not energize-next-use-from-mark)
  166.       (setq energize-next-use-from-mark (make-marker)))
  167.   (set-marker energize-next-use-from-mark 
  168.           (extent-start-position extent) buffer))
  169.  
  170. (defun energize-next-use-init (command label)
  171.   ;; start-offset is the position of point if it is in the LEB buffer
  172.   (let ((start-offset (energize-next-use-start-pos-offset)))
  173.     (if (not (eq major-mode 'energize-browser-mode))
  174.     (if (energize-list-menu (current-buffer)
  175.                 (energize-extent-at (point)) ()
  176.                 "browse_le")
  177.         (energize-execute-command "browse_le"
  178.                       (energize-extent-at (point)) () t)
  179.       (error
  180.        "command undefined unless in a LE buffer or at a LE definition form")))
  181.     (setq energize-next-use-command-name command)
  182.     (setq energize-next-use-label label)
  183.     (setq energize-next-use-current-file nil)
  184.     (setq energize-next-use-from-extent-cache nil)
  185.     (setq energize-next-use-history nil)
  186.     (setq energize-next-use-history-pointer nil)
  187.     (let* ((pos (energize-next-use-start-pos))
  188.        (extent (and pos
  189.             ;; start at the beginning, unless start-pos says
  190.             ;; to start further along
  191.             (energize-next-use-adjust-for-start-offset
  192.              (extent-after pos) start-offset))))
  193.       (if (null extent)
  194.       (error "no uses")
  195.     (energize-next-use-set-marks extent (current-buffer))
  196.     (setq energize-next-use-name
  197.               (save-excursion
  198.                 (let ((s (energize-next-use-get-name (buffer-name))))
  199.                   (if (let ((l (length s)))
  200.                         (while (not
  201.                                 (and (> l 0)
  202.                                      (progn
  203.                                        (beginning-of-buffer)
  204.                                        (search-forward
  205.                                         (substring s 0 l) nil t))))
  206.                           (setq l (- l 1)))
  207.                         (> l 0))
  208.                       (let (pos)
  209.                         (backward-sexp)
  210.                         (setq pos (point))
  211.                         (forward-sexp)
  212.                         (buffer-substring pos (point)))
  213.                     s))))))
  214.     (energize-next-use-show-both)))
  215.  
  216. (defun energize-next-use-end-pos ()
  217.   (save-excursion
  218.     (goto-char (point-min))
  219.     (search-forward energize-next-use-label)
  220.     (re-search-forward "^ *[A-Za-z ]*: " () 'end)
  221.     (point)))
  222.  
  223. ;; return the source-entry portion of the extent cache, looking it up
  224. ;; if necessary by doing energize-execute-command "source" on the extent
  225. ;; source-entry portion is list of
  226. ;; a) point marker after executing the "source" command
  227. ;; b) a flag saying we've actually visited this use, not just looked it up
  228. ;; c) marker for the window-start after executing the "source" command
  229. (defun energize-next-use-from-extent-source-info (from-extent-entry)
  230.   (let ((extent (car from-extent-entry))
  231.     (source-entry (cdr from-extent-entry)))
  232.     (if (not source-entry)
  233.     (save-window-excursion
  234.       (save-excursion
  235.         (let ((pre-display-buffer-function nil)) ;; hack for multi-frame
  236.           (energize-execute-command
  237.            energize-next-use-command-name extent () t))
  238.         (setcdr from-extent-entry
  239.             (setq source-entry
  240.               (list (energize-next-use-copy-a-marker
  241.                  (point-marker))
  242.                 nil
  243.                 (set-marker
  244.                  (energize-next-use-make-a-marker)
  245.                  (window-start))))))))
  246.     source-entry))
  247.  
  248. (defun energize-next-use-from-extent-source-mark (source-entry)
  249.   (car source-entry))
  250.  
  251. (defun energize-next-use-from-extent-source-start-mark (source-entry)
  252.   (car (cdr (cdr source-entry))))
  253.  
  254. (defun energize-next-use-from-extent-source-seen-p (source-entry)
  255.   (car (cdr source-entry)))
  256.  
  257. (defun energize-next-use-from-extent-set-source-seen-p (source-entry)
  258.   (setcar (cdr source-entry) t))
  259.  
  260. ;; goto the next user - or if advance is nil try to re-establish the
  261. ;; extent for the current one
  262. (defun energize-next-use-next-to-extent (advance)
  263.   (let ((buff (marker-buffer energize-next-use-from-mark))
  264.     (from-pos (marker-position energize-next-use-from-mark)))
  265.     (and buff from-pos
  266.      (let ((result nil))
  267.        (set-buffer buff)
  268.        (let ((end-pos (energize-next-use-end-pos))
  269.          (extent (or (energize-extent-at from-pos)
  270.                  (setq advance nil)
  271.                  (extent-after from-pos))))
  272.          (if (and advance energize-next-use-search-by-file)
  273.          (if (not energize-next-use-current-file)
  274.              ;; if searching by file but dont have a current file,
  275.              ;; set current file to current source buffer
  276.              (if (setq energize-next-use-current-file
  277.                    (and energize-next-use-source-start-mark
  278.                     (marker-buffer
  279.                      energize-next-use-source-start-mark)))
  280.              (progn
  281.                (if (not energize-next-use-file-began-mark)
  282.                    (setq energize-next-use-file-began-mark
  283.                      (make-marker)))
  284.                (set-marker energize-next-use-file-began-mark
  285.                        from-pos buff))))
  286.            (setq energize-next-use-current-file nil))
  287.          (if advance
  288.          (setq extent (next-extent extent)))
  289.          (if energize-next-use-search-by-file
  290.          (message "Searching for next use in current file...")
  291.            (message "Searching for next use..."))
  292.          ;; validate the extent
  293.          (while extent
  294.            (while
  295.            (and
  296.             extent
  297.             ;; if extent is beyond the end of the "used by" zone
  298.             ;; set it to nil to terminate loop
  299.             (or (< (extent-start-position extent) end-pos)
  300.             (setq extent nil))
  301.             (not
  302.              (let ((from-extent-entry
  303.                 (energize-next-use-valid-from-extent-p
  304.                  buff extent)))
  305.                (and
  306.             ;; true if the extent has a "source" menu option
  307.             from-extent-entry
  308.             (or
  309.              (not energize-next-use-search-by-file)
  310.              ;; see if this is extent points to the current file
  311.              ;; or a file we haven't looked at yet, if not current
  312.              ;; file is set now
  313.              (let* ((source-entry
  314.                  (energize-next-use-from-extent-source-info
  315.                   from-extent-entry))
  316.                 (source-marker
  317.                  (energize-next-use-from-extent-source-mark
  318.                   source-entry))
  319.                 (buff (marker-buffer source-marker)))
  320.                (if energize-next-use-current-file
  321.                    (eq buff energize-next-use-current-file)
  322.                  (not
  323.                   (energize-next-use-from-extent-source-seen-p
  324.                    source-entry)))))))))
  325.          (setq extent (next-extent extent)))
  326.            (if extent
  327.            ;; we found one we can use - remember it but set extent
  328.            ;; to nil to terminate the loop
  329.            (progn
  330.              ;; convert the extent to a mark for future reference
  331.              (energize-next-use-set-marks extent buff)
  332.              ;; terminate the loop
  333.              (setq extent nil)
  334.              ;; saw we succeeded in finding something
  335.              (setq result t))
  336.          ;; we didn't find anything valid - if we were looking in
  337.          ;; the current file, restart the loop now looking for
  338.          ;; anything we haven't used yet, to make it the current file
  339.          ;; if we weren't looking in the current file then we really
  340.          ;; have failed to find anything left, so return nil
  341.          (if energize-next-use-current-file
  342.              (progn
  343.                (setq energize-next-use-current-file nil)
  344.                (setq extent
  345.                  ;; restart loop from were we started looking at
  346.                  ;; the current file
  347.                  (let ((pos (marker-position
  348.                      energize-next-use-file-began-mark)))
  349.                    (and pos
  350.                     (or (energize-extent-at pos)
  351.                     (extent-after pos)))))))))
  352.          (if energize-next-use-search-by-file
  353.          (message "Searching for next use in current file...done")
  354.            (message "Searching for next use...done"))
  355.          result)))))
  356.  
  357. (defun energize-next-use-show-from (&optional mark)
  358.   (setq mark (or mark energize-next-use-from-mark))
  359.   (if energize-next-use-show-le-browser
  360.       ;; position the browser to the line of the current user
  361.       (let ((buff (marker-buffer mark))
  362.         (from-pos (marker-position mark)))
  363.     (and buff from-pos
  364.          (progn
  365.            ;; don't worry about pre-display-buffer-function here;
  366.            ;; we actually want a new frame to be created when
  367.            ;; displaying the Browser buffer.
  368.            (pop-to-buffer buff)
  369.            (goto-char from-pos)
  370.            (beginning-of-line)
  371.            (set-window-start (selected-window) (point)))))
  372.     (message "next use of %s" energize-next-use-name)))
  373.  
  374. (defun energize-next-use-show-to ()
  375.   (let* ((buff (marker-buffer energize-next-use-from-mark))
  376.      (from-pos (marker-position energize-next-use-from-mark))
  377.      (from-extent (and buff from-pos (energize-extent-at from-pos buff)))
  378.      (from-extent-entry
  379.       ;; get the cache entry for the current user extent in the browser
  380.       (energize-next-use-valid-from-extent-p buff from-extent))
  381.      (source-extent nil))
  382.     (and
  383.      from-extent-entry
  384.      (let* ((source-entry
  385.          (energize-next-use-from-extent-source-info
  386.           from-extent-entry))
  387.         (source-marker
  388.          (energize-next-use-from-extent-source-mark
  389.           source-entry))
  390.         (source-buffer (marker-buffer source-marker))
  391.         (source-pos (marker-position source-marker))
  392.         ;; if we're allowed to split frames, call pop-to-buffer
  393.         ;; with no pre-display-buffer-function, so that the current
  394.         ;; frame (the frame of the Browser buffer) is used.  If
  395.         ;; we don't split frames, then use the p-d-b-f, so that a
  396.         ;; new frame can be created for this file.
  397.         (pre-display-buffer-function
  398.          (if energize-split-screens-p
  399.          nil
  400.            pre-display-buffer-function)))
  401.        (if source-pos
  402.        (progn
  403.          ;; position the source window as if we had just executed the
  404.          ;; command "source" on the from-extent in the browser
  405.          (pop-to-buffer source-buffer)
  406.          (set-window-start
  407.           (selected-window)
  408.           (marker-position
  409.            (energize-next-use-from-extent-source-start-mark source-entry))
  410.           t)
  411.          (goto-char source-marker)
  412.          ;; note that we have actually visited this use
  413.          (energize-next-use-from-extent-set-source-seen-p source-entry)
  414.          (setq source-extent (energize-extent-at (point))))))
  415.      (let ((start-pos (extent-start-position source-extent)))
  416.        ;; convert positions to markers
  417.        (if (not energize-next-use-source-start-mark)
  418.        (setq energize-next-use-source-start-mark (make-marker)))
  419.        (if (not energize-next-use-source-end-mark)
  420.        (setq energize-next-use-source-end-mark (make-marker)))
  421.        (if (not energize-next-use-source-current-mark)
  422.        (setq energize-next-use-source-current-mark (make-marker)))
  423.        (set-marker energize-next-use-source-start-mark start-pos)
  424.        (set-marker energize-next-use-source-current-mark start-pos)
  425.        (set-marker energize-next-use-source-end-mark
  426.            (extent-end-position source-extent))))))
  427.  
  428. (defun energize-next-use-search-for-name ()
  429.   (if (let ((case-fold-search nil)
  430.         (found nil)
  431.         (end-pos (marker-position energize-next-use-source-end-mark)))
  432.     (if end-pos
  433.         (progn
  434.           (buffer-syntactic-context-flush-cache)
  435.           ;; case sensitive exact search for token not in comment or string
  436.           (while
  437.           (and
  438.            (setq found
  439.              (re-search-forward
  440.               (concat "[^A-Za-z0-9_]"
  441.                   (regexp-quote energize-next-use-name)
  442.                   "[^A-Za-z0-9_]")
  443.               end-pos t))
  444.            (save-excursion (buffer-syntactic-context))))))
  445.     found)
  446.       (progn
  447.     ;; allow for the delimiter
  448.     (backward-char 1)
  449.     t)
  450.     nil))
  451.  
  452.  
  453. ;; say this if search can't find the thing that is being used
  454. (defun energize-next-use-not-lexically-apparent ()
  455.   (message "next use of %s is here, but not lexically apparent"
  456.        energize-next-use-name))
  457.  
  458. ;; called when visiting a new users, not a new use within that user
  459. (defun energize-next-use-show-both ()
  460.   ;; reposition the browser to the line showing the user
  461.   (energize-next-use-show-from)
  462.   ;; position the source to the user definition form
  463.   (energize-next-use-show-to)
  464.   ;; instead of stopping at the beginning of the user form,
  465.   ;; go immediately to the first use found if it is lexically apparent
  466.   (if (and
  467.        energize-next-use-source-start-mark
  468.        (let ((buff (marker-buffer energize-next-use-source-start-mark))
  469.          (current-pos
  470.           (marker-position energize-next-use-source-current-mark))
  471.          (end-pos (marker-position energize-next-use-source-end-mark)))
  472.      (if (and buff current-pos end-pos)
  473.          (save-excursion
  474.            (set-buffer buff)
  475.            (and (< current-pos end-pos)
  476.             (progn
  477.               (goto-char current-pos)
  478.               (energize-next-use-search-for-name)))))))
  479.       ;; an apparent use is there, so proceed as if going to the next use
  480.       ;; within the user
  481.       (energize-next-use-next)
  482.     ;; no use is apparent, so print a message
  483.     (energize-next-use-not-lexically-apparent)
  484.     ;; record the history entry for a non-apparent use - it is distinguished
  485.     ;; by having no point position from which to make a region to highlight
  486.     (setq energize-next-use-history
  487.       (cons (list (energize-next-use-copy-a-marker
  488.                energize-next-use-from-mark)
  489.               (energize-next-use-copy-a-marker
  490.                energize-next-use-source-current-mark)
  491.               (set-marker (energize-next-use-make-a-marker)
  492.                   (window-start)))
  493.         energize-next-use-history))
  494.     (setq energize-next-use-history-pointer
  495.       energize-next-use-history)))
  496.  
  497. ;; show the next use within the current user - if no more are found
  498. ;; go to the next user
  499. (defun energize-next-use-next ()
  500.   ;; new-start will get set to an extent for a user at which to
  501.   ;; reposition the visit, iff the cursor is in the LEB buffer
  502.   ;; of the usee at a valid position in the list of users.
  503.   (let ((new-start (energize-next-use-adjust-for-start-offset
  504.             nil (energize-next-use-start-pos-offset)))
  505.     (buff (marker-buffer energize-next-use-source-start-mark))
  506.     (current-pos (marker-position energize-next-use-source-current-mark))
  507.     (end-pos (marker-position energize-next-use-source-end-mark)))
  508.     (if (and buff (not (eq buff (current-buffer))))
  509.     (set-buffer buff))
  510.     ;; new-start means we are repositioning due to the point being in the
  511.     ;; user list in the browser.  In this case we will act as if we are
  512.     ;; at the end of the old user
  513.     (if new-start
  514.     (energize-next-use-set-marks
  515.      new-start
  516.      (marker-buffer energize-next-use-from-mark)))
  517.     (cond ((and buff current-pos end-pos
  518.         (not new-start) ;; don't stay in current user if repositioning
  519.         (< current-pos end-pos)
  520.         (progn
  521.           (goto-char current-pos)
  522.           (energize-next-use-search-for-name)))
  523.        ;; the 'still in the same user' case
  524.        (set-marker energize-next-use-source-current-mark (point))
  525.        ;; redisplay the browser in case it got covered up
  526.        (energize-next-use-show-from)
  527.        ;; We know that we're not changing files, so there won't be any
  528.        ;; need to create a new frame; it would be nice if we reselected
  529.        ;; the appropriate frame instead of just using the current frame,
  530.        ;; but that's more work, and this will very rarely do the wrong
  531.        ;; thing.
  532.        (let ((pre-display-buffer-function 
  533.           (if energize-split-screens-p
  534.               nil
  535.             pre-display-buffer-function)))
  536.          ;; display the source buffer
  537.          (pop-to-buffer buff)
  538.          ;; had to do this because window-start overrides point
  539.          ;; in terms of deciding what part of the window to show
  540.          ;; this seems like a possible bug
  541.          (set-window-buffer (selected-window) buff)
  542.          (push-mark (point) t)
  543.          (backward-char (length energize-next-use-name))
  544.          (if zmacs-regions
  545.          (zmacs-activate-region))
  546.          ;; record the visit in the history - this entry has a point
  547.          ;; marker, distinguishing it from a non-lexically apparent one
  548.          (setq energize-next-use-history
  549.            (cons (list
  550.               (energize-next-use-copy-a-marker
  551.                energize-next-use-from-mark)
  552.               (energize-next-use-copy-a-marker
  553.                energize-next-use-source-current-mark)
  554.               (set-marker (energize-next-use-make-a-marker)
  555.                       (window-start))
  556.               (set-marker (energize-next-use-make-a-marker)
  557.                       (point)))
  558.              energize-next-use-history))
  559.          (setq energize-next-use-history-pointer
  560.            energize-next-use-history)))
  561.       ((or new-start
  562.            (energize-next-use-next-to-extent
  563.         (and buff current-pos end-pos)))
  564.        ;; the 'moved to a new user or repositioned to one' case
  565.        (energize-next-use-show-both))
  566.       (t
  567.        ;; no more users
  568.        (energize-next-use-terminate)
  569.        (error "no more")))))
  570.  
  571.  
  572. (defun energize-next-use-terminate ()
  573.   (setq energize-next-use-command-name ())
  574.   (setq energize-next-use-label ())
  575.   (setq energize-next-use-name ())
  576.   (if energize-next-use-from-mark
  577.       (set-marker energize-next-use-from-mark nil))
  578.   (if energize-next-use-source-start-mark
  579.       (set-marker energize-next-use-source-start-mark nil))
  580.   (if energize-next-use-source-current-mark
  581.       (set-marker energize-next-use-source-current-mark nil))
  582.   (if energize-next-use-source-end-mark
  583.       (set-marker energize-next-use-source-end-mark nil))
  584.   (if energize-next-use-file-began-mark
  585.       (set-marker energize-next-use-file-began-mark nil))
  586.   (energize-next-use-cleanup-markers))
  587.  
  588. ;; get next use from history list if we have regressed or are regressing
  589. ;; if history-pointer == history then we are in the present
  590. ;; to go back set history-pointer to cdr history-pointer
  591. ;; to go forward set history-pointer to the last cell on history prior to
  592. ;; the current value of history-pointer
  593. ;; a history entry is just redisplay info for the browser and source buffers
  594. (defun energize-next-use-from-history (backward)
  595.   (if backward
  596.       (setq energize-next-use-history-pointer
  597.         (cdr energize-next-use-history-pointer))
  598.     (let ((temp energize-next-use-history-pointer))
  599.       (setq energize-next-use-history-pointer
  600.         energize-next-use-history)
  601.       (while (not (eq (cdr energize-next-use-history-pointer) temp))
  602.     (setq energize-next-use-history-pointer
  603.           (cdr energize-next-use-history-pointer)))))
  604.   (let* ((history-entry (car energize-next-use-history-pointer))
  605.      (from-mark (car history-entry))
  606.      (source-mark (car (cdr history-entry)))
  607.      (source-start-mark (car (cdr (cdr history-entry))))
  608.      (source-point-mark (car (cdr (cdr (cdr history-entry))))))
  609.     (energize-next-use-show-from from-mark)
  610.     (if (and (marker-position source-mark)
  611.          (marker-position source-start-mark))
  612.     (progn
  613.       (pop-to-buffer (marker-buffer source-mark))
  614.       (set-window-start
  615.        (selected-window) (marker-position source-start-mark) t)
  616.       (goto-char source-mark)
  617.       (if (and source-point-mark (marker-position source-point-mark))
  618.           (progn
  619.         (push-mark (point) t)
  620.         (goto-char source-point-mark)
  621.         (if zmacs-regions
  622.             (zmacs-activate-region)))
  623.         (energize-next-use-not-lexically-apparent))))))
  624.  
  625. (defun energize-next-use-go (label command)
  626.   (if (and energize-next-use-from-mark
  627.        (marker-position energize-next-use-from-mark))
  628.       (if (eq energize-next-use-history-pointer
  629.           energize-next-use-history)
  630.       ;; normal case
  631.       (energize-next-use-next)
  632.     ;; in the depths of history but going forward
  633.     (energize-next-use-from-history nil))
  634.     ;; beginning of time
  635.     (energize-next-use-init label command)))
  636.  
  637. (defun energize-next-use-previous ()
  638.   (if (cdr energize-next-use-history-pointer)
  639.       ;; going back in time
  640.       (energize-next-use-from-history t)
  641.     ;; trying to go beyond the pale
  642.     (error "no prior use")))
  643.     
  644. (defun energize-next-use-command (arg)
  645.   "Show the next place where the current language element is used.
  646. The current language element is the one that point is on for source buffers
  647. or the element displayed in a language element browser buffer.
  648. Repeated calls to this functions visit all the callers in sequence.  
  649.  
  650. With prefix arg = 1, back up to the last use.
  651.  
  652. With prefix arg > 1, start a visit from scratch on the current language 
  653. element.
  654.  
  655. If the point is on a particular user in the language element browser, the
  656. search will be (re)started in that user.
  657.  
  658. The variable energize-next-use-show-le-browser controls if this command should
  659. display both the language element browser buffer and the next user or just the
  660. next user of the current language element.
  661.  
  662. The variable energize-next-use-search-by-file controls whether all uses within
  663. a given file should be shown in sequence.  If the value is nil, the uses
  664. are shown in the order in which they appear in the LE Browser.  If the
  665. value is non-nil, the all uses in a given file are shown before proceeding to
  666. the next use in another file."
  667.   (interactive "P")
  668.   (if (eq arg 1)
  669.       (energize-next-use-previous)
  670.     (if arg
  671.     (energize-next-use-terminate))
  672.     (energize-next-use-go "source" "Used By:")))
  673.  
  674. (define-key global-map '[(control x) \\] 'energize-next-use-command)
  675.  
  676. (defun energize-next-use-start ()
  677.   "Start visiting the uses of a language element.
  678. If executed in a LE Browser buffer visit the uses of the language element
  679. in the buffer.  In a source buffer visit the uses of the language element
  680. at (point)"
  681.   (interactive)
  682.   (energize-next-use-command 4))
  683.